/*
 * Copyright 2007-2010 Jeremy Brown.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author <a href="http://jeremy-brown.com">Jeremy Brown</a>
 */


package groovy.prefuse.factory

import prefuse.activity.*
import prefuse.controls.*
import prefuse.data.event.*
import prefuse.util.*
import prefuse.data.io.*
import prefuse.util.display.*

import groovy.util.FactoryBuilderSupport;

import java.awt.event.*
import javax.swing.event.*

public class ListenerFactory extends AbstractFactory
{
	private Class klass

	public ListenerFactory(Class klass)
	{
		this.klass = klass
	}
	
	boolean isLeaf()
	{
		return true
	}
    
    public Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException
	{
    	//println("ListenerFactory: name:$name, value:$value, attributes:$attributes, klass:$klass")
    	
    	builder.context.put("nodeName", name)
    			
		def values = null
		if(value == null)
		{
			if(attributes.listener)
			{
				value = attributes.remove("listener")
			}
			else if(attributes.adapter)
			{
				value = attributes.remove("adapter")
			}
			else if((attributes.size() > 0 && attributes.id == null) || attributes.size() > 1)
			{
				values = [:]
				attributes.each{key, val->
					//don't consume the id attribute
					if(key != "id")
					{
						values.put(key, val)
					}
				}
				values.each{key, val->
					attributes.remove(key)
				}
			}
		}

		
		if(value instanceof ActivityListener || 
			value instanceof ColumnListener ||
			value instanceof ComponentListener ||
			value instanceof ControlAdapter ||
			value instanceof ExpressionListener ||
			value instanceof GraphListener ||
			value instanceof ItemBoundsListener ||
			value instanceof MouseListener ||
			value instanceof MouseInputListener ||
			value instanceof MouseMotionListener ||
			value instanceof MouseWheelListener ||
			value instanceof PaintListener ||
			value instanceof ProjectionListener ||
			value instanceof TableListener ||
			value instanceof TableReadListener ||
			value instanceof TupleSetListener ||
			value instanceof UpdateListener
			)
		{
			return value
		}

		if(values)
		{
			value = values
		}

		def buildClass
		if(klass)
		{
			buildClass = klass
		}
		else if(value instanceof Class)
		{
			buildClass = value
			value = null
		}

		def listener = null

		if(buildClass instanceof Class)
		{
			if(value == null && attributes.listener)
			{
				value = attributes.remove("listener")
			}
			else if(value == null && attributes.adapter)
			{
				value = attributes.remove("adapter")
			}
			else if(value == null && attributes)
			{
				value = [:]
		        attributes.each{key,val-> 
		        	if(key != "id")
		        	{
		        		value[key] = val
		        	}
				}
				attributes.clear()
			}

			if(value instanceof Map)
			{
				if(buildClass.isAssignableFrom(UpdateListener) && value.update)
				{
					//An UpdateListener with the update: attribute assigned
					if(buildClass.isAssignableFrom(ExpressionListener))
					{
						listener = (value as UpdateListener) as ExpressionListener
					}
					else if(buildClass.isAssignableFrom(TupleSetListener))
					{
						listener = (value as UpdateListener) as TupleSetListener
					}
					else if(buildClass.isAssignableFrom(ComponentListener))
					{
						listener = (value as UpdateListener) as ComponentListener
					}
					else
					{
						listener = value as UpdateListener
					}
				}
				else if(buildClass.isAssignableFrom(ActivityListener))
				{
					listener = value as ActivityAdapter
				}
				else if(buildClass.isAssignableFrom(ColumnListener))
				{
					listener = value as ColumnListener
				}
				else if(buildClass.isAssignableFrom(ComponentListener))
				{
					listener = value as ComponentAdapter
				}
				else if(buildClass.isAssignableFrom(ControlAdapter))
				{
					listener = value as ControlAdapter
				}
				else if(buildClass.isAssignableFrom(ExpressionListener))
				{
					listener = value as ExpressionListener
				}
				else if(buildClass.isAssignableFrom(GraphListener))
				{
					listener = value as GraphListener
				}
				else if(buildClass.isAssignableFrom(ItemBoundsListener))
				{
					listener = value as ItemBoundsListener
				}
				else if(buildClass.isAssignableFrom(MouseListener))
				{
					listener = value as MouseAdapter
				}
				else if(buildClass.isAssignableFrom(MouseInputListener))
				{
					listener = value as MouseInputAdapter
				}
				else if(buildClass.isAssignableFrom(MouseMotionListener))
				{
					listener = value as MouseMotionAdapter
				}
				else if(buildClass.isAssignableFrom(MouseWheelListener))
				{
					listener = value as MouseWheelListener
				}
				else if(buildClass.isAssignableFrom(PaintListener))
				{
					listener = value as PaintListener
				}
				else if(buildClass.isAssignableFrom(ProjectionListener))
				{
					listener = value as ProjectionListener
				}
				else if(buildClass.isAssignableFrom(TableListener))
				{
					listener = value as TableListener
				}
				else if(buildClass.isAssignableFrom(TableReadListener))
				{
					listener = value as TableReadListener
				}
				else if(buildClass.isAssignableFrom(TupleSetListener))
				{
					listener = value as TupleSetListener
				}
			}
		}
		return listener
	}

	public void onNodeCompleted(FactoryBuilderSupport builder, Object parent, Object child) 
	{
		addNodeToParent(builder, parent, child)
    }

	public void addNodeToParent(FactoryBuilderSupport builder, Object parent, Object child)
	{
		def nodeName = builder.context.nodeName - "pf"

		//find method to use by the node name used to create this node
		switch(nodeName)
		{
			case "ActivityListener": parent.addActivityListener(child); break
			case "ColumnListener": parent.addColumnListener(child); break
			case "ComponentListener": parent.addComponentListener(child); break
			case "ControlListener": parent.addControlListener(child); break
			case "ExpressionListener": parent.addExpressionListener(child); break
			case "GraphListener": parent.addGraphListener(child); break
			case "ItemBoundsListener": parent.addItemBoundsListener(child); break
			case "MouseListener": parent.addMouseListener(child); break
			case "MouseInputListener": parent.addMouseInputListener(child); break
			case "MouseMotionListener": parent.addMouseMotionListener(child); break
			case "MouseWheelListener": parent.addMouseWheelListener(child); break
			case "PaintListener": parent.addPaintListener(child); break
			case "ProjectionListener": parent.addProjectionListener(child); break
			case "TableListener": parent.addTableListener(child); break
			case "TableReadListener": parent.addTableReadListener(child); break
			case "TupleSetListener": parent.addTupleSetListener(child); break
			case "UpdateListener": addUpdateListenerToParent(parent, child); break
			case "Listener":
			default: //used when the node is pfListener
				//find method to use by the class of the child
				if(child instanceof ActivityListener){parent.addActivityListener(child)}
				else if(child instanceof ColumnListener){parent.addColumnListener(child)}
				else if(child instanceof ComponentListener){parent.addComponentListener(child)}
				else if(child instanceof ControlAdapter){parent.addControlListener(child)}
				else if(child instanceof ExpressionListener){parent.addExpressionListener(child)}
				else if(child instanceof GraphListener){parent.addGraphListener(child)}
				else if(child instanceof ItemBoundsListener){parent.addItemBoundsListener(child)}
				else if(child instanceof MouseListener){parent.addMouseListener(child)}
				else if(child instanceof MouseInputListener){parent.addMouseInputListener(child)}
				else if(child instanceof MouseMotionListener){parent.addMouseMotionListener(child)}
				else if(child instanceof MouseWheelListener){parent.addMouseWheelListener(child)}
				else if(child instanceof PaintListener){parent.addPaintListener(child)}
				else if(child instanceof ProjectionListener){parent.addProjectionListener(child)}
				else if(child instanceof TableListener){parent.addTableListener(child)}
				else if(child instanceof TableReadListener){parent.addTableReadListener(child)}
				else if(child instanceof TupleSetListener){parent.addTupleSetListener(child)}
				else if(child instanceof UpdateListener)
				{
					addUpdateListenerToParent(parent, child)
				}
		}//switch
	}



	public void addUpdateListenerToParent(Object parent, Object child)
	{
		if(child.componentHidden != null || child.componentResized != null || child.componentShown != null || child.update != null)
		{
			try
			{
				parent.addComponentListener(child)
			}
			catch(Exception e){}
		}
		
		if(child.expressionChanged != null || child.update != null)
		{
			try
			{
				parent.addExpressionListener(child)
			}
			catch(Exception e){}
		}

		if(child.tupleSetChanged != null || child.update != null)
		{
			try
			{
				parent.addTupleSetListener(child)
			}
			catch(Exception e){}
		}
	}

}
